/*
 * Field.cpp
 *
 *  Created on: 04-Sep-2014
 *      Author: ali
 */

#include "Field.h"
#include "Constant.h"
#include "NodeContainer.h"

struct STAT gStat;
Field::Field(int nLen, int nWidth) :
		m_nLength(nLen), m_Width(nWidth)
{
}

Node Field::GetNearestSink(Quarter qtr)
{
	Coordinate mid = qtr.GetMid();

	std::vector<Node>::iterator itSink = m_vectorSink.begin();
	Node nearestnode = *itSink;
	double dLeastDis = -1, curDis = -1;

	for (std::vector<Node>::iterator itSink = m_vectorSink.begin();
			itSink != m_vectorSink.end(); ++itSink)
	{
		Node curnode = *itSink;
		curDis = mid.GetDistance(curnode.GetPos());
		if (-1 == dLeastDis)
		{
			dLeastDis = curDis;
		}
		if (curDis < dLeastDis)
		{
			dLeastDis = curDis;
			nearestnode = curnode;
		}
	}
	return nearestnode;
}

void Field::AddSink(Node node)
{
	m_vectorSink.push_back(node);
}
bool Field::SendData()
{
	bool bStat = false;
	for (vector<Quarter>::iterator itQtr = m_vectorQuarter.begin();
			itQtr != m_vectorQuarter.end(); ++itQtr)
	{
		Quarter &qtr = (*itQtr);
		bStat = qtr.SendData();
	}
	return bStat;
}
bool Field::SelectCH()
{
	bool bStat = false;
	int chqtrselection = 0;
	for (vector<Quarter>::iterator itQtr = m_vectorQuarter.begin();
			itQtr != m_vectorQuarter.end(); ++itQtr)
	{
		Quarter &qtr = (*itQtr);
		bStat = qtr.SelectCH();
		if (false == bStat)
		{
			++chqtrselection;
		}
	}
	if (m_vectorQuarter.size() == chqtrselection)
	{
		bStat = false;
	}
	else
	{
		bStat = true;
	}
	return bStat;
}

int Field::MultiHopIteration(int nRoundCount)
{
	int nRound = 0;
	int iActiveNodeCount = 0;

	double dNewPower = 0;
	double dOldPower = NodeContainer::GetCurrentResidualPower();
	gStat.dPACKETTOBS = 0;
	gStat.dPACKETTOCH = 0;
	while (nRoundCount--)
	{

		gStat.dCHCount= 0;

		bool bStat = false;
		bStat = SelectCH();
		bStat = SendData();
		dNewPower = NodeContainer::GetCurrentResidualPower();
		iActiveNodeCount = NodeContainer::GetActiveNodeCount();

		cout << "Round # " << ++nRound << " Active node count "
				<< iActiveNodeCount << " Current Residual power " << dNewPower
				<< " Power Spent " << dOldPower - dNewPower <<
				" PACKETTOBS " <<  gStat.dPACKETTOBS <<
				" PACKETTOCH " <<  gStat.dPACKETTOCH <<
				" CHCount " <<  gStat.dCHCount <<
				endl << endl
				<< endl;
		if (dNewPower <= 0)
		{
			cout << "No More Round possible. All power spent." << endl;
			break;
		}
		if (iActiveNodeCount == 0)
		{
			cout << "No More Round possible. All Node dead." << endl;
			break;
		}
		dOldPower = dNewPower;
	}
	return nRound;
}
void Field::AddSensor(Node node)
{
	NodeContainer::PutNode(node.GetID(), &node);
	for (vector<Quarter>::iterator itQtr = m_vectorQuarter.begin();
			itQtr != m_vectorQuarter.end(); ++itQtr)
	{
		Quarter &qtr = (*itQtr);

		if (qtr.IsCoordinateInside(node.GetPos()))
		{
			qtr.AddSensor(node);
			return;
		}
	}
}

void Field::AddQuarter(Quarter quarter)
{
	Node sink = GetNearestSink(quarter);
	quarter.AddSink(sink);
	m_vectorQuarter.push_back(quarter);

}
const int Field::GetLength()
{
	return m_nLength;
}
const int Field::GetWidth()
{
	return m_Width;
}

Field::~Field()
{
}
ostream & operator<<(ostream &out, Field& f)
{

	for (vector<Quarter>::iterator itQtr = f.m_vectorQuarter.begin();
			itQtr != f.m_vectorQuarter.end(); ++itQtr)
	{
		Quarter &qtr = (*itQtr);
		out << qtr;
	}
	return out;
}

